package org.opu.doc2db.document.txtdoc.io;

import java.util.ArrayList;
import java.util.List;

import org.opu.doc2db.document.datadocument.Metric;
import org.opu.doc2db.document.datadocument.Table;
import org.opu.doc2db.document.datadocument.TableCell;
import org.opu.doc2db.document.datadocument.TableRow;
import org.opu.doc2db.document.datadocument.TextParagraph;

public class SettingsCalculator {

    /**
     * Return array of column number, that are nullable.
     *
     * @param table
     *            where to find
     * @return array of column number, that are nullable.
     */
    public Integer[] nullCollumn(Table table) {
        List<Integer> ret = new ArrayList<Integer>();

        try {
            TableRow row = table.elementsGet(0);
            int iter = 0;
            for (TableCell cell : row) {
                if (!cell.isVisible()) {
                    ret.add(iter);
                }
                iter++;
            }
        } catch (Exception e) {
        }

        return ret.toArray(new Integer[ret.size()]);
    }

    /**
     * Return true if arr contain i value.
     *
     * @param i
     *            value
     * @param arr
     *            array of diget data
     * @return true if arr contain i value.
     */
    public boolean isIn(int i, Integer arr[]) {
        for (int val : arr) {
            if (i == val) {
                return true;
            }
        }

        return false;
    }

    /**
     * Added to string necessary space at the and, that it length was like in metric.
     * If string to long, it trimmed and returned.
     *
     * @param str
     *            processing string
     * @param metric
     *            metric with it length (metrics name don`t analysis)
     * @return string
     */
    public String toOptimal(String str, Metric<Integer> metric) {
        if (str.length() > metric.getMetric()) {
            str = str.trim();
        }

        if (str.length() >= metric.getMetric()) {
            return str;
        }

        return add(str, TextDocumentWriter.SPACE, metric.getMetric() - str.length());
    }

    /**
     * Return current string with adding to specific character define time.
     *
     * @param str
     *            current string (can be null, if it null it`s same that empty)
     * @param ch
     *            specific character
     * @param count
     *            number of adding (define time)
     * @return current string with adding to specific character define time.
     */
    public String add(String str, char ch, int count) {

        StringBuilder sb = new StringBuilder();

        if (str != null) {
            sb.append(str);
        }

        if (count > 0) {
            for (int i = 0; i < count; i++) {
                sb.append(ch);
            }
        }

        return sb.toString();
    }

    /**
     * Defines table width, it`s width is width of longer row.
     *
     * @param table
     *            table width of we defines
     * @return table width
     */
    public int tableWidth(Table table) {
        int[] cw = columnWidth(table);
        int total = 0;

        for (int i = 0; i < cw.length; i++) {
            total += cw[i];
        }

        total += (cw.length - 1);

        try {
            TableRow row = table.elementsGet(0);
            for (int i = row.elementsSize() - 1; i > 0; i--) {
                TableCell cell = row.elementsGet(i);
                if (cell.isVisible()) {
                    total += ((row.elementsSize() - 1) - i);
                    break;
                } else {
                    total -= (cell.getWidthMetric() + 1);
                }
            }
        } catch (Exception e) {
        }

        return total;

    }

    /**
     * Return string with new line
     *
     * @param str
     *            input string (can be null)
     * @return string with new line
     */
    public String getNewLine(String str) {
        if (str == null) {
            str = "";
        }
        return str + System.getProperty("line.separator");
    }

    /**
     * Return list of text in cell
     *
     * @param aditional aditional data (can be null)
     * @param cell
     *            processed cell
     * @param start
     *            is it needed to added end of cell character to start
     *            (last collumn in row ...)
     * @param end
     *            is it needed to added end of cell character to end
     *            (last collumn in row ...)
     * @return list of text in cell
     */
    public List<String> toList(List<String> aditional, TableCell cell, boolean start, boolean end) {
        List<TextParagraph> elements = cell.getElements();
        List<String> data = new ArrayList<String>();

        if (aditional != null) {
            data.addAll(aditional);
        }

        for (TextParagraph p : elements) {
            data.add((start ? TextDocumentWriter.CEL_SEPARATOR : "") // cell start
                    + toOptimal(p.getText(), cell.getWidth()) // cell data
                    + (end ? TextDocumentWriter.CEL_SEPARATOR : ""));//cell end
        }

        return data;
    }

    /**
     * Return array of column widths
     *
     * @param table
     *            table
     * @return array of column widths
     */
    public int[] columnWidth(Table table) {
        int index = 0;
        int max = 0, maxindex = 0;

        // trye to find longest row and it index
        for (TableRow row : table) {
            if (row.elementsSize() > max) {
                max = row.elementsSize();
                maxindex = index;
            }
            index++;
        }

        int arr[];

        // get width of each column
        try {
            TableRow row = table.elementsGet(maxindex);
            arr = new int[row.elementsSize()];
            index = 0;
            for (TableCell c : row) {
                arr[index++] = c.getWidthMetric();
            }
        } catch (Exception e) {
            arr = new int[]{};
        }

        return arr;
    }

    /**
     * Return cell that under current cell, or null if it cell at first row.
     *
     * @param table
     *            table where it`s cell was
     * @param cell
     *            cell parent of wot needed to find
     * @param row
     *            number of row where it (start from 0)
     * @return cell that under current cell, or null if it cell at first row.
     */
    public TableCell cellParent(Table table, TableCell cell, int row) {
        if (row < 1 || row >= table.elementsSize()) {
            return null;
        }

        int num = 0;
        TableRow trow = table.elementsGet(row);
        for (TableCell c : trow) {
            if (c.equals(cell)) {
                break;
            } else {
                num += c.getHsplit();
            }
        }

        trow = table.elementsGet(row - 1);
        int pos = 0;
        for (TableCell c : trow) {
            pos += c.getHsplit();

            if (pos >= num) {
                return c;
            }
        }

        // default return last cell.
        return trow.elementsGet(trow.elementsSize() - 1);

    }
}
